const compileUtil = {
  getVal(expr, vm){
    return expr.split('.').reduce((data, currentVal) => {
      debugger
      return data[currentVal];
    }, vm.$data)
  },
  text(node, expr, vm){
    // expr: msg
    const value = this.getVal(expr, vm);
    this.undater.textUpdater(node, value)
  },
  html(node, expr, vm){
    let value
    if(expr.indexOf('{{') != -1){
      // {{a}} {{person.name}}
      let ex = /\{\{(.+?)\}\}/g
      value = expr.replace(ex, (...args) => {
        console.log(args)
      })
    }else {
      value = this.getVal(expr, vm)
    }
    
    this.undater.htmlUpdater(node, value)
  },
  model(node, expr, vm){
    const value = this.getVal(expr, vm)
    this.undater.modelUpdater(node, value)
  },
  on(node, expr, vm, eventName){

  },
  // 更新的函数
  undater: {
    textUpdater(node, value){
      node.textContent = value;
    },
    htmlUpdater(node, value){
      node.innerHTML = value;
    },
    modelUpdater(node, value){
      node.value = value;
    }
  }
}
class Compile {
  constructor(el, vm) {
    // 判断el是否为元素节点对象
    this.el = this.isElementNode(el) ? el : document.querySelector(el)
    this.vm = vm;
    // 获取文档碎片对象，放入内存中，减少页面回流和重绘
    const fragment = this.node2Fragment(this.el)
    // 编译模板
    this.compile(fragment)
    // 追加子元素到根元素
    this.el.appendChild(fragment)
  }

  compile(fragment) {
    // 获取子节点
    const childNodes = fragment.childNodes;
    [...childNodes].forEach(child => {
      if(this.isElementNode(child)){
        // 是否是元素节点
        // 编译元素节点
        // console.log('元素节点', child)
        this.compileElement(child)
      }else {
        // 文本节点
        // 编译文本节点
        // console.log('文本节点', child)
        this.compileText(child)
      }
      // 是否还有子节点，若还有，继续遍历
      if(child.childNodes && child.childNodes.length > 0){
        this.compile(child)
      }
    })
  }

  compileElement(node){
    const attributes = node.attributes;
    [...attributes].forEach(attr => {
      const {name, value} = attr;
      if(this.isDirective(name)){
        // 是一个指令
        const [,directive] = name.split('-');
        const [dirName,eventName] = directive.split(':');
        // 数据驱动视图
        compileUtil[dirName](node, value, this.vm, eventName)
        // 删除有指令的标签上的属性
        node.removeAttribute('v-' + directive)
      }
    });
  }

  compileText(node){
    const content = node.textContent;
    let ex = /\{\{(.+?)\}\}/
    if(ex.test(content)){
      compileUtil['text'](node, content, this.vm)
    }
  }

  isDirective(attrName){
    return attrName.startsWith('v-')
  }

  node2Fragment(el){
    // 创建文档碎片
    const f = document.createDocumentFragment();
    let firstChild;
    while(firstChild = el.firstChild){
      f.appendChild(firstChild);
    }
    return f
  }

  isElementNode(node){
    return node.nodeType === 1
  }
}
class MVue {
  constructor(options) {
    this.$el = options.el;
    this.$data = options.data;
    this.$options = options;
    if(this.$el){
      // 实现数据观察者
      // 实现指令解析器
      new Compile(this.$el, this)

    }
  }
}







let vm = new MVue({
  el: '#app',
  data: {
    person: {
      name: 'oliver',
      age: 18,
      fav: 'man'
    },
    msg: 'gan',
    htmlStr: 'kakakakak'
  }
})